/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */

package org.bhf.service.view;

import org.bhf.json.JSONWriter;
import org.bhf.service.Constants;
import org.bhf.service.ProcessView;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

/**
 * This view renders the return object in JSON.
 * <p>If the reponse has already been committed, such as setting a redirect before processing the view, this
 * <code>ProcessView</code>, will do nothing as the reponse has effectively already been handled.</p>
 */
public class JSONProcessView implements ProcessView
{
    private     Object        result;
    protected   JSONWriter    writer;

    /**
     * Render the given object in JSON with a state set of 0.
     * @param result The result object to be rendered in JSON. May be <code>null</code>
     */
    public JSONProcessView( final Object result )
    {
        this.writer = new JSONWriter();
        this.result = result;
    }

    /**
     * Render the given object in JSON with a state set of 0.
     * @param service Service object
     * @param method The target service method
     * @param result The result object to be rendered in JSON. May be <code>null</code>
     */
    public JSONProcessView( final Object service, final Method method,  final Object result )
    {
        this( result );
    }

    /**
     * ProcessView contract.
     *
     * @param request Servlet request.
     * @param response Serlvet reponse.
     * @param servletContext The servlet context for this application
     * @throws java.io.IOException ConversionError during JSON rendering
     * @exclude
     */
    public void processView( final HttpServletRequest request, final HttpServletResponse response, final ServletContext servletContext )
        throws IOException
    {
        if( response.isCommitted() )
            return;

        final StringBuffer json = new StringBuffer( getJSON() );
        final String callback = request.getParameter( Constants.SUCCESS_CALLBACK_PARAMETER );

        response.setContentType( "text/javascript" );

        if( callback != null )
        {
            json.insert( 0, callback + "(" );
            json.append( ")" );
        }

        response.setContentLength( json.length() );
        final PrintWriter out = response.getWriter();
        out.print( json.toString() );
        out.close();
    }

    //
    // Subclass Contract
    //

    protected JSONProcessView( final JSONWriter writer )
    {
        this.writer = writer;
    }

    public Object getResult()
    {
        return result;
    }

    public void setResult( Object result )
    {
        this.result = result;
    }

    /**
     * Retrieve the JSON representation of this result. If result is null, this
     * method will return null.
     * @return The JSON representation of this result. If result is null, this
     * method will return null.
     * @throws java.io.IOException ConversionError during JSON rendering
     * @exclude
     */
    protected String    getJSON()
        throws IOException
    {
        if( result == null )
            return "null";
        else if( result == Constants.VOID )
            return "undefined";
        else
            return writer.writeObject( result );
    }
}